package com.wedimob.plugins.scrapper;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import net.xeoh.plugins.base.annotations.PluginImplementation;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import com.wedimob.bo.SerializableBO;
import com.wedimob.common.Language;
import com.wedimob.content.Content;
import com.wedimob.plugins.PluginType;
import com.wedimob.query.SearchCriteria;
import com.wedimob.query.SearchType;
import com.wedimob.query.SortBy;

@PluginImplementation
public class SlideShareScrapper implements Scrapper {

	public final static String URL_BASE = "http://fr.slideshare.net";
	public final static String SEARCH_PATTERN = URL_BASE + "/search";
	public final static String USER_PAGE_PATTERN = URL_BASE + "/{username}";
	public final static String USER_DOC_PAGE_PATTERN = URL_BASE
			+ "/{username}/slideshelf";
	private final static double NB_ITEM_PER_PAGE = 12.0;

	@Override
	public PluginType type() {
		return PluginType.PARSER;
	}

	@Override
	public String id() {
		return SlideShareScrapper.class.getName();
	}

	@Override
	public URI url() {
		return URI.create("http://scrapperframework.googlecode.com/");
	}

	@Override
	public String version() {
		return "1.0.0";
	}

	@Override
	public URI screenshot() {
		return URI
				.create("http://public.slidesharecdn.com/images/header-11/slideshare-logo.png");
	}

	@Override
	public String title(Locale locale) {
		return "Slideshare parser";
	}

	@Override
	public String author() {
		return "mohamed.elouadi";
	}

	@Override
	public String company() {
		return "wedimob";
	}

	@Override
	public String email() {
		return "mohamed.elouadi@gmail.com";
	}

	@Override
	public String description(Locale locale) {
		switch (Language.fromLocale(locale)) {
		case FR:
			return "";

		case EN:
		default:
			return "";
		}
	}

	@Override
	public Calendar publicationDate() {
		Calendar publicationDate = Calendar.getInstance();
		int year = 2013;
		int month = Calendar.MARCH;
		int date = 9;
		publicationDate.set(year, month, date, 12, 0);
		return publicationDate;
	}

	@Override
	public String whatsnew(Locale locale) {
		switch (Language.fromLocale(locale)) {
		case FR:
			return "";

		case EN:
		default:
			return "";
		}
	}

	@Override
	public List<String> history(Locale locale) {
		return Collections.emptyList();
	}

	@Override
	public boolean accept(SearchCriteria criteria, Content content) {
		return content.getUri().toString().startsWith(URL_BASE);
	}

	@Override
	public boolean islist(SearchCriteria criteria, Content content) {
		return content.getUri().toString().startsWith(SEARCH_PATTERN);
	}

	@Override
	public SerializableBO<?> single(SearchCriteria criteria, Content content) {
		if (islist(criteria, content))
			throw new RuntimeException("Try to parse a list content");

		switch (criteria.getSearchType()) {
		case CONTENT:
			return parseSingleContent(content);
		case USER:
			return parseSingleAuthor(content);
		default:
			throw new RuntimeException("Cannot handle type "
					+ criteria.getSearchType());
		}
	}

	static private Document getDocument(Content content) {
		try {
			return Jsoup.parse(content.getInputStream(), null, content
					.getUri().toASCIIString());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	static private SerializableBO<?> parseSingleAuthor(Content content) {
		return null;
	}

	static private SerializableBO<?> parseSingleContent(Content content) {
		return null;
	}

	static private List<SerializableBO<?>> parseListAuthor(Content content) {
		return null;
	}

	static private List<SerializableBO<?>> parseListContent(Content content) {
		return null;
	}

	@Override
	public List<SerializableBO<?>> list(SearchCriteria criteria, Content content) {
		if (!islist(criteria, content))
			throw new RuntimeException("Try to parse a single content");

		switch (criteria.getSearchType()) {
		case CONTENT:
			return parseListContent(content);
		case USER:
			return parseListAuthor(content);
		default:
			throw new RuntimeException("Cannot handle type "
					+ criteria.getSearchType());
		}
	}

	private static int getNbPages(int limit, double itemPerPage) {
		return Math.max(1, (int) Math.ceil(limit / itemPerPage));
	}

	@Override
	public List<URI> uris(SearchCriteria criteria) {
		try {
			List<URI> result = new ArrayList<URI>();
			int nbPages = getNbPages(criteria.getLimit(), NB_ITEM_PER_PAGE);
			int begin = (int) Math
					.floor(criteria.getBegin() / NB_ITEM_PER_PAGE);
			for (int i = begin; i < begin + nbPages; i++) {
				result.add(URI.create(URL_BASE + "/search/"
						+ convert(criteria.getSearchType())
						+ "?lang=%2A%2A&page=" + (i + 1) + "&q="
						+ criteria.getKeyword().replaceAll(" ", "+")
						+ "&searchfrom=header&sort="
						+ convert(criteria.getSortBy())));
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private String convert(SortBy sortBy) {
		switch (sortBy) {
		case RELEVANCE:
			return "relevance";
		case LAST_PUBLICATION:
			return "tout dernier";
		case POPULARITY:
			return "vues";
		}
		return null;
	}

	private String convert(SearchType type) {
		switch (type) {
		case CONTENT:
			return "slideshow";
		case USER:
			return "user";
		}
		throw new RuntimeException("Cannot handle type " + type);
	}

	@Override
	public int maxConcurrentAccess() {
		return 10;
	}

}
